import * as CANNON from 'cannon-es'
import { ShapeType, threeToCannon } from 'three-to-cannon'
export default class CannonWorld {
  constructor() {
    this.init()
  }
  init() {
    console.error('init  CannonWorld========>')
    this.instance = new CANNON.World()
    this.instance.gravity.set(0, -9.82, 0)
    this.instance.broadphase = new CANNON.SAPBroadphase(this.instance)
    this.instance.allowSleep = true
    this.material = {}
    this.floor
    this.createeMaterial()
    this.createFloor()
  }
  createeMaterial() {
    this.material.concreteMaterial = new CANNON.Material('concrete') //创建混凝土材质
    this.material.plasticMaterial = new CANNON.Material('plastic') //创建塑料材质
    const cannonDefaultCantactMaterial = new CANNON.ContactMaterial(this.material.concreteMaterial, this.material.plasticMaterial, {
      friction: 0.1, //摩擦力
      restitution: 0.1, //反弹力
    })
    this.instance.addContactMaterial(cannonDefaultCantactMaterial)
  }

  createFloor() {
    this.floor = new CANNON.Body({
      mass: 0, //质量
      position: new CANNON.Vec3(0, 0, 0), //位置
      //刚体的形状。 CANNON.Sphere为圆球体  CANNON.Box为立方体 更多形状查看文档：https://pmndrs.github.io/cannon-es/docs/classes/Shape.html
      shape: new CANNON.Plane(),
      //材质  材质决定了物体(刚体)的弹力和摩擦力，默认为null，无弹力无摩擦。 plastic为塑料材质  concrete为混泥土材质。相关文档地址：https://pmndrs.github.io/cannon-es/docs/classes/Material.html
      material: this.material.concreteMaterial,
    })
    //添加外力，这有点类似于风力一样，在某个位置向某物吹风
    // 该方法接收两个参数：force：力的大小(Vec3)    relativePoint：相对于质心施加力的点(Vec3)。
    // this.floor.applyForce(new CANNON.Vec3(100, 0, 0), this.floor.position)
    // 由于平面初始化是是竖立着的，所以需要将其旋转至跟现实中的地板一样 横着
    // 在cannon.js中，我们只能使用四元数(Quaternion)来旋转，可以通过setFromAxisAngle(…)方法，第一个参数是旋转轴，第二个参数是角度
    this.floor.quaternion.setFromAxisAngle(new CANNON.Vec3(-1, 0, 0), Math.PI * 0.5)
    this.instance.addBody(this.floor)
  }

  // 绘制threejs物体对应的物理物体
  createMesh(object3D) {
    const { shape, offset, quaternion } = threeToCannon(object3D, { type: ShapeType.BOX })
    const body = new CANNON.Body({
      mass: 10, //质量
      position: new CANNON.Vec3(object3D.position.x, object3D.position.y, object3D.position.z),
      material: this.material.plasticMaterial,
    })
    body.addShape(shape)
    this.instance.addBody(body)
    return body
  }

  update() {
    this.instance.fixedStep() //动态更新world
  }
}
